using System;
using System.Configuration;
using System.Web;
using System.Xml;
using System.Xml.Xsl;

/*	-----------------------------------------------------------------------	
	Copyright:	umlungu consulting (pty) ltd
	Author:		Alan Benington	
	Started:	2006-03-08	
	Status:		release	
	Version:	2.0.0
	Buidl:		20070524
	License:	GNU General Public License
	-----------------------------------------------------------------------	*/

/*	-----------------------------------------------------------------------	
	Development Notes:
	 -	This Class has the following hierarchy:
		  uiX
			|_ pageX
				|_ System.Web.UI.Page
	 -	This class is responsible for the loading of the page Xml, the Xsl 
	 	template and the rendering to html. The loading and rendering process
		is contained in the BlogIt method which is typically the single call
		in the top-level .aspx file called by the url.
	 -	Errors are handled by the raising an x_glitch exception that it caught 
	 	within the BlogIt method.
	 -	This class contains empty _ProcessAction and _LoadAdditional methods
	 	which are typically overridden in derived classes to provide unique 
		handling actions.
	20070524:	Modification for .Net 2.0
	20070703:	Removed net_2_0 directive (from compatibility build)
	---------------------------------------------------------------------------	*/


namespace umlungu.engineX.blogX {
	/// <summary>Type of blog page to be displayed - identified by the 'page' url parameter</summary>
	public enum x_blogPageType {
		/// <summary>default type</summary>
	    def = 0,
		/// <summary>'space' type</summary>
	    space = 1,
		/// <summary>'archive' type</summary>
	    archive = 2,
		/// <summary>'author' type</summary>
	    author = 3,
		/// <summary>'home' type</summary>
		home = 4,
		/// <summary>'press' type</summary>
		press = 5,
		/// <summary>'response' type</summary>
		response = 6,
		/// <summary>'response' type</summary>
		sitemap = 7,
		/// <summary>'other' type</summary>
		other = 8
	}
	/// <summary>Type of blog identifiers - identified by the 'id' or 'ids' url parameters</summary>
	public enum x_blogIDType {
		/// <summary>no 'id' or 'ids' defined</summary>
	    none = 0,
		/// <summary>a single id defined</summary>
	    single = 1,
		/// <summary>multiple id's defined</summary>
	    multiple = 2
	}
	/// <summary>
	/// umlungu engineX blog page base class.
	/// </summary>
	public class uiX : pageX {
		#region Invisible properties
		#endregion

		#region Visible properties
		private x_blogspace blogspace;
		/// <summary>The blogspace of the blog</summary>
		/// <value>Description of the value of the property</value>
		public x_blogspace Space {
			get { return blogspace; }
			set { blogspace = value; }
		}
		private x_result error;
		/// <summary>The error result object</summary>
		/// <value>Description of the value of the property</value>
		public x_result ErrorResult {
			get { return error; }
			set { error = value; }
		}
		private XslCompiledTransform template;
		/// <summary>The blogspace xsl template</summary>
		/// <value>Description of the value of the property</value>
		public XslCompiledTransform Template {
			get { return template; }
			set { template = value; }
		}
		/// <summary></summary>
		/// <value></value>
		public XmlElement Blogs { 
			get { return _blogs.DocumentElement; } 
		}
		/// <summary></summary>
		/// <value></value>
		public XmlElement Blogspace { 
			get { return blogspace.Blogspace; } 
		}
		private string blogname;
		/// <summary>The blogspace name</summary>
		/// <value></value>
		public string Name { 
			get { return blogname; } 
		}
		private string blogid;
		/// <summary>The identifier</summary>
		/// <value></value>
		public string BlogID { 
			get { return blogid; }	
			set	{ blogid = value; } 
		}
		private string blogtopic;
		/// <summary>The blogspace name</summary>
		/// <value></value>
		public string Topic { 
			get { return blogtopic; } 
			set	{ blogtopic = value; } 
		}
		private string blogarchive;
		/// <summary>The blogspace name</summary>
		/// <value></value>
		public string Archive { 
			get { return blogarchive; } 
		}
		private string blogids;
		/// <summary>The selected blog ids</summary>
		/// <value></value>
		public string BlogIDs { 
			get { return blogids; } 
		}
		private string blogauthor;
		/// <summary>The blogspace name</summary>
		/// <value></value>
		public string Author { 
			get { return blogauthor; } 
		}
		private string blogpage;
		/// <summary>The page</summary>
		/// <value>The value of the page set by the url 'page' parameter</value>
		public string BlogPage {
			get { return blogpage; }
			set { blogpage = value; }
		}
		private x_blogPageType pageType;
		/// <summary>The page type</summary>
		/// <value>The type of the page set by the url 'page' parameter</value>
		public x_blogPageType PageType {
			get { return pageType; }
			set { pageType = value; }
		}
		private x_blogIDType idType;
		/// <summary>The id type</summary>
		/// <value>The type of the id set by the url 'id' or 'ids' parameter</value>
		public x_blogIDType IDType {
			get { return idType; }
			set { idType = value; }
		}
		private XmlElement blog;
		/// <summary>The blog element</summary>
		/// <value>An XmlElement containing the blog defintion</value>
		public XmlElement Blog { 
			get { return blog; }
			set	{ blog = value; }
		}
		private XmlDocument _blogs;
		/// <summary>The blog page xml</summary>
		/// <value>The XmlDocument that contains the blog page xml</value>
		public XmlDocument BlogXml {
			get { return _blogs; }
			set { _blogs = value; }
		}
		private XsltArgumentList templateArgs;
		/// <summary>Definiton of the property</summary>
		/// <value>Description of the value of the property</value>
		public XsltArgumentList TemplateArgs {
			get { return templateArgs; }
			set { templateArgs = value; }
		}
		#endregion

		#region Constructors/Destructors
		/// <over_Loads>Constructor</over_Loads>
		/// <summary>Default constructor</summary>
		public uiX() : this ("uiX") {
		}
		/// <summary>Constructor supplyiong class name identifier</summary>
		/// <param name="lbl">Name to be used in error and debugging messages</param>
		public uiX(string lbl) : base(lbl) {
			template = new XslCompiledTransform();     
			_blogs = new XmlDocument();
		}
		#endregion

		#region Public methods
		/// <summary>Renders the blog to the UI</summary>
		public virtual void BlogIt() {
			try {
				_LoadIt();
				_ProcessAction();
				BlogLoad();
				if (Debugger.Enabled)
					showPage(_blogs.OuterXml);
				else
					showPage();
			}
			catch(x_glitch g) {
				try {
					_LoadIt(g);
					BlogLoad(g);
					if (Debugger.Enabled)
						showPage(_blogs.OuterXml);
					else
						showPage();
				} catch (System.Exception e) {
					error = new x_result("BlogX");
					showPage(error.AddError(e).OuterXml);
				}
			}
			catch(x_exception e) {
				error = new x_result("BlogX");
				showPage(error.AddError(e).OuterXml);
			}
			catch(System.Exception e) {
				error = new x_result("BlogX");
				showPage(error.AddError(e).OuterXml);
			}
		}
		/// <summary>Test the rendering of the blog</summary>
		public void BlogTest() {
			string xslfile = Server.MapPath("test.xsl");
			string xmlfile = Server.MapPath("test.xml");
			template.Load(xslfile);
			_blogs.Load(xmlfile);
			template.Transform(_blogs, null, Response.Output);
		}
		
		#endregion

		#region Protected methods
		/// <summary>
		/// Processes an action defined by the submission of a form with the 'Action' field. 
		///	This method is typically overriden in derived classesfor specific form handling.
		/// </summary>
		protected virtual void _ProcessAction() {
		}
		/// <overloads>Loads parameters, template and additional xml</overloads>
		/// <summary>Default loader</summary>
		protected virtual void _LoadIt() {
			_LoadParameters();
			_LoadTemplate();
		}
		/// <summary>Glitch loader</summary>
		/// <param name="glitch">The object that defines the glitch to be loaded</param>
		protected virtual void _LoadIt(x_glitch glitch) {
			_LoadParameters(glitch);
			_LoadTemplate();
		}
		/// <overloads>Blog loader</overloads>
		/// <summary>Blog loader</summary>
		protected void BlogLoad() {
			_LoadContent(true);
			decodeContent();
		}
		/// <summary>Glitch loader</summary>
		/// <param name="glitch">The object that defines the glitch to be loaded</param>
		protected void BlogLoad(x_glitch glitch) {
			_LoadContent(false);
			decodeContent();
		}
		/// <overloads>Loads the parameters that drive the blog content</overloads>
		/// <summary>Default loader. Parameters defined in the url querystring</summary>
		protected virtual void _LoadParameters() {
			blogname = Request.QueryString["name"];
			if (blogname == null)
				blogname = Config.Space;
			if (blogname == null)
				throw(new x_exception("errorblogspace_name", "blogspace is not defined ('name' parameter missing?)"));
			blogpage = (Request.QueryString["page"] == null)? "default" : Request.QueryString["page"];
			blogtopic = (Request.QueryString["topic"] == null)? "" : Request.QueryString["topic"];
			blogarchive = (Request.QueryString["archive"] == null)? "" : Request.QueryString["archive"];
			blogid = Request.QueryString["id"];
			blogids = Request.QueryString["ids"];
			blogauthor = Request.QueryString["author"];
			_loadParameterTypes();
		}
		/// <summary>Glitch loader. Parameters defined in the glitch object</summary>
		/// <param name="glitch">The object that defines the glitch to be loaded</param>
		protected virtual void _LoadParameters(x_glitch glitch) {
			blogname = glitch.Space;
			if (blogname == null)
				throw(new x_exception("errorblogspace_name", "blogspace is not defined ('name' parameter missing?)"));
			blogpage = glitch.Page;
			blogtopic = glitch.Topic;
			blogarchive = glitch.Archive;
			blogid = glitch.Blog;
			blogids = glitch.Blogs;
			blogauthor = glitch.Author;
			_loadParameterTypes();
		}
		/// <summary>
		/// Loads the blog xsl
		/// </summary>
		protected virtual void _LoadTemplate() {
			Debugger.Spoor("_LoadTemplate", "pageType", pageType.ToString());
			blogspace = new x_blogspace(Application);
			if (pageType == x_blogPageType.sitemap) {
				blogspace.Get(blogname);
				getTemplate("sitemapX.xsl");
			} else
				template = blogspace.GetTransform(blogname);
			//	Add xsl parameters.
			templateArgs = new XsltArgumentList();
			templateArgs.AddParam("name", "", blogname);
			templateArgs.AddParam("page", "", blogpage);
			templateArgs.AddParam("topic", "", blogtopic);
			templateArgs.AddParam("archive", "", blogarchive);
			templateArgs.AddParam("topics", "", blogspace.Blogspace.SelectSingleNode("//topics").CreateNavigator());
			templateArgs.AddParam("space", "", blogspace.Blogspace.CreateNavigator());
		}
		/// <summary>
		/// Loads any additional stuff. 
		///	This method is typically overriden in derived classes that require special extension to the loaded xml 
		/// </summary>
		protected virtual void _LoadAdditional() {
		}
		/// <summary>Loads the blog xml</summary>
		protected virtual void _LoadContent() {
			_LoadContent(true);
		}
		/// <summary>Loads the blog xml</summary>
		protected virtual void _LoadContent(bool additional) {
			Debugger.Spoor("_LoadContent", "pageType", pageType.ToString());
			switch(pageType) {
				case x_blogPageType.space:		_LoadBlogspace();		break;
				case x_blogPageType.archive:	_LoadBlogArchives();	break;
				case x_blogPageType.author:		_LoadAuthor();			break;
				default:						_LoadBlogTopic();		break;
			}
			if (additional)
				_LoadAdditional();
		}
		/// <summary>
		/// Loads the blogspace xml
		/// </summary>
		protected virtual void _LoadBlogspace() {
			_blogs.LoadXml(blogspace.Blogspace.OuterXml);
		}
		/// <summary>
		/// Loads the blogspace archives xml
		/// </summary>
		protected virtual void _LoadBlogArchives() {
			blogspace.Archives(blogname);
			_blogs.LoadXml(blogspace.Blogspace.OuterXml);
		}
		/// <summary>
		/// Loads the author xml
		/// </summary>
		protected virtual void _LoadAuthor() {
			x_user userx = new x_user(Application, blogauthor);
			XmlNode thisuser = blogspace.Blogspace.SelectSingleNode(String.Concat("//users/user[@name='", blogauthor, "']"));
			thisuser.InnerXml = userx.User.InnerXml;
			userx.GetBlog(blogauthor);
			thisuser.InnerXml = String.Concat(thisuser.InnerXml, userx.User.OuterXml);
			_blogs.LoadXml(blogspace.Blogspace.OuterXml);
			//_blogs.LoadXml(userx.User.OuterXml);
		}
		/// <summary>
		/// Loads the blog xml defined by topic
		/// </summary>
		protected virtual void _LoadBlogTopic() {
			Debugger.Spoor("_LoadBlogTopic", "blogtopic", blogtopic);
			Debugger.Spoor("_LoadBlogTopic", "idType", idType.ToString());
			if (blogtopic == "")
				_LoadAll();
			else {
				switch(idType) {
					case x_blogIDType.single:	_LoadBlog();		break;
					case x_blogIDType.multiple:	_LoadBlogs();		break;
					case x_blogIDType.none:
					default:					_LoadBlogList();	break;
				}
			}
		}
		/// <summary>
		/// Loads a blog xml
		/// </summary>
		protected virtual void _LoadAll() {
			blogspace.Current(blogname);
			_blogs.LoadXml(blogspace.Blogspace.OuterXml);
		}
		/// <summary>
		/// Loads a blog xml
		/// </summary>
		protected virtual void _LoadBlog() {
			x_blog thisblog = new x_blog(Application);
			if (blogarchive == "")
				thisblog.Get(blogname, blogtopic, blogid);
			else
				thisblog.Get(blogname, blogtopic, blogarchive, System.Convert.ToInt32(blogid));
			_blogs.LoadXml(thisblog.Blog.OuterXml);
			_blogs.DocumentElement.InnerXml = blogspace.Blogspace.OuterXml + _blogs.DocumentElement.InnerXml;
		}
		/// <summary>
		/// Loads the blog xml
		/// </summary>
		protected virtual void _LoadBlogs() {
			x_blog thisblog = new x_blog(Application);
			if (blogarchive == "")
				thisblog.Gets(blogname, blogtopic, blogids, true, true);
			else
				thisblog.Gets(blogname, blogtopic, blogarchive, blogids, true, true);
			_blogs.LoadXml(thisblog.Blogs.OuterXml);
			_blogs.DocumentElement.InnerXml = blogspace.Blogspace.OuterXml + _blogs.DocumentElement.InnerXml;
		}
		/// <summary>
		/// Loads the blog xml
		/// </summary>
		protected virtual void _LoadBlogList () {
			x_blog thisblog = new x_blog(Application);
			thisblog.List(blogname, blogtopic);
			_blogs.LoadXml(thisblog.Blogs.OuterXml);
			_blogs.DocumentElement.InnerXml = blogspace.Blogspace.OuterXml + _blogs.DocumentElement.InnerXml;
		}
		#endregion

		#region Private methods
		/*
		/// <summary>
		/// Loads the blog xml
		/// </summary>
		private void decodeContent() {
			foreach (XmlNode textnode in _blogs.SelectNodes("//blog/text")){
				XmlElement textel = (XmlElement) textnode;
				textel.SetAttribute("decoded", "yes");
				textel.InnerXml = (textel.GetAttribute("type") == "html" || textel.GetAttribute("html") == "yes")? HttpUtility.HtmlDecode(textel.InnerText) : HttpUtility.HtmlDecode(textel.InnerXml);
			}
		}
		*/
		/// <summary>
		/// Decodes the content within blog xml (similar to the displayX  base class)
		/// </summary>
		private void decodeContent() {
			// the following is for backward compatability
			foreach (XmlNode textnode in _blogs.SelectNodes("//blog/text")){
				XmlElement textel = (XmlElement) textnode;
				textel.SetAttribute("decoded", "yes");
				textel.InnerXml = (textel.GetAttribute("type") == "html" || textel.GetAttribute("html") == "yes")? HttpUtility.HtmlDecode(textel.InnerText) : HttpUtility.HtmlDecode(textel.InnerXml);
			}
			foreach (XmlNode textnode in _blogs.SelectNodes("//blog/bloghtml")){
				XmlElement textel = (XmlElement) textnode;
				textel.SetAttribute("decoded", "yes");
				textel.InnerXml = HttpUtility.HtmlDecode(textel.InnerText);
			}
			foreach (XmlNode textnode in _blogs.SelectNodes("//blog/blogtext")){
				XmlElement textel = (XmlElement) textnode;
				textel.SetAttribute("decoded", "yes");
				textel.InnerXml = HttpUtility.HtmlDecode(textel.InnerXml);
			}
		}
		/// <summary>
		/// Loads the blogPageType and blogIDType (from the url parameters)
		/// </summary>
		private void _loadParameterTypes() {
			_loadPageType();
			_loadIDType();
		}
		/// <summary>
		/// Loads the blogPageType
		/// </summary>
		private void _loadPageType() {
			switch(blogpage) {
				case "space":		pageType = x_blogPageType.space;	break;
				case "archive":		pageType = x_blogPageType.archive;	break;
				case "author":		pageType = x_blogPageType.author;	break;
				case "home":		pageType = x_blogPageType.home;		break;
				case "press":		pageType = x_blogPageType.press;	break;
				case "response":	pageType = x_blogPageType.response;	break;
				case "sitemap":		pageType = x_blogPageType.sitemap;	break;
				case "other":		pageType = x_blogPageType.other;	break;
				case "default":
				case "":
				default:			pageType = x_blogPageType.def;		break;
			}
		}
		/// <summary>
		/// Loads the blogIDType
		/// </summary>
		private void _loadIDType() {
			if (blogids != null && blogids != "")
				idType = x_blogIDType.multiple;
			else if (blogid != null && blogid != "")
				idType = x_blogIDType.single;
			else
				idType = x_blogIDType.none;
		}
		/// <summary>show the page as html</summary>
		private void showPage() {
			Response.ContentType = (pageType == x_blogPageType.sitemap)? "text/xml" : "text/html";
			template.Transform(_blogs, templateArgs, Response.Output);
		}
		/// <summary>show the page as xml</summary>
		private void showPage(string xml) {
			Response.ContentType = "text/xml";
			Response.Write(xml);
		}
		/// <summary>
		/// Loads the xsl template for special types (ie not the normal content xsl)
		/// </summary>
		private void getTemplate(string thistype) {
			string templFile = String.Concat(blogspace.Path, blogname, "/", thistype);
			//string templFile = Server.MapPath(String.Concat("templates/", thistype));
			template.Load(templFile);
		}
		#endregion
	}
}
